home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
embedded
/
68hc11
/
fuzzy11a.arc
/
FUZZY11A.ASM
next >
Wrap
Assembly Source File
|
1991-12-04
|
9KB
|
241 lines
* Fuzzy Logic Inferrence Engine
*
*** Data structures and variables
*
ORG $0000 ;Beginning of HC11 RAM
CURRENT_INS RMB 8 ;Storage for 8 8-bit inputs
FUZ_OUTS RMB 32 ;Storage for fuzzy outputs
COG_OUTS RMB 4 ;Defuzzified outputs
LOWEST_IF RMB 1 ;Holds min grade of IF parts
SUM_OF_FUZ RMB 2 ;11-bit sum of fuzzy outs
SUM_OF_PROD RMB 3 ;19-bit sum of products
COGDEX RMB 1 ;Current out # for COG loop 0->4
SUMDEX RMB 1 ;Index for sum loop 8->0
ORG $B600 Beginning of HC11 EEPROM
IN_MF_PTRS FDB IN0MF ;Addr of MF data for input 0
FDB IN1MF ;Addr of MF data for input 1
FDB IN2MF ;Addr of MF data for input 2
FDB IN3MF ;Addr of MF data for input 3
FDB IN4MF ;Addr of MF data for input 4
FDB IN5MF ;Addr of MF data for input 5
FDB IN6MF ;Addr of MF data for input 6
FDB IN7MF ;Addr of MF data for input 7
*
* Input membership functions are defined by four 8-bit values per
* input label. Up to 8 labels per input so max size of MF data
* structure is 8*8*4=256 bytes. Unused labels take no space.
* Membership functions are trapezoids with the base greater than or
* equal to the top. Values are entered into this program as the
* X coordinates of 4 points but are stored as 2 points and 2 slopes.
*
***** MACRO Definition for input membership functions
*
INMF MACR ;For input membership functions
FCB \0 ;First inflection point
IFNE \1-\0 ;Check for divide by zero
FCB ($FF+((\1-\0)/3))/(\1-\0) ;If not, calc slope
ENDC
IFEQ \1-\0 ;Check for divide by zero
FCB $00 ;Indicates vertical slope
ENDC
FCB \2 ;Third inflection point
IFNE \3-\2 ;Check for divide by zero
FCB ($FF+((\3-\2)/3))/(\3-\2) ;If not, calc slope
ENDC
IFEQ \3-\2 ;Check for divide by zero
FCB $00 ;Indicates vertical slope
ENDC
ENDM
*
*****
INPUT_MFS EQU * ;Input membership functions
IN0MF EQU * ;(0) ROTATION
INMF 0,0,0,8*4 ; (0) STOPPED
INMF 0,8*4,$FF,$FF ; (1) NOT_STOPPED
IN1MF EQU * ;(1) EXAMPLE1
INMF $20,$40,$60,$A0 ; (0) TEST1
IN2MF EQU * ;(2) TEMPERATURE
INMF 2*0,2*0,2*40,2*50 ; (0) COLD
INMF 2*40,2*50,2*60,2*70 ; (1) COOL
INMF 2*60,2*70,2*80,2*90 ; (2) WARM
INMF 2*80,2*90,2*95,2*110 ; (3) HOT
INMF 2*90,2*110,$FF,$FF ; (4) VERY_HOT
IN3MF EQU * ;(3) DAYS_SINCE_RAIN
INMF $00,$00,$00,$08 ; (0) NONE
INMF $00,$10,$10,$18 ; (1) SHORT
INMF $10,$20,$28,$40 ; (2) MEDIUM
INMF $30,$40,$50,$60 ; (3) LONG
INMF $50,$70,$FF,$FF ; (4) VERY_LONG
IN4MF EQU * ;Not used
IN5MF EQU * ;Not used
IN6MF EQU * ;Not used
IN7MF EQU * ;Not used
SGLTN_POS EQU * ;Output singleton positions
OUT0MF EQU * ;(0) WATERING_TIME
FCB $00 ;(0) CUT_OFF
FCB $10 ;(1) DECREASE_GREATLY
FCB $40 ;(2) DECREASE
FCB $80 ;(3) NORMAL
FCB $B0 ;(4) INCREASE
FCB $F0 ;(5) INCREASE_GREATLY
FCB 0,0 ;Unused; Must fill 8 per output
OUT1MF FCB 0,0,0,0,0,0,0,0 ;Not used
OUT2MF FCB 0,0,0,0,0,0,0,0 ;Not used
OUT3MF FCB 0,0,0,0,0,0,0,0 ;Not used
*
* Each If part is of the form 00AA AXXX where AAA is a label (0-7)
* and XXX is an input (0-7). If parts are connected by ANDs. A rule
* may have any number of if parts (usually 2-8). Then parts are of
* the form 100Y YCCC where the MSB set indicates a then part, YY is
* the output number (0-3), and CCC is the output label (singleton
* 0-7). A rule may have any number of then parts (usually 1 or 2).
* A $FF indicates the end of a series of rules (number not limited).
*
* FCB INx + 8*LABa ;If input XXX is label AAA
* FCB $80+8*OUTy+LABc ;Then output YY is label CCC
RULE_START EQU * ;Start of first rule
* Example rule: If TEMPERATURE is VERY_HOT and DAYS_SINCE_RAIN is LONG
* Then WATERING_TIME is INCREASE_GREATLY
RULE_1 FCB 2+(8*4),3+(8*3),$80+(8*0)+5
END_OF_RULE FCB $FF
***** Fuzzy Inferrence Engine Starts Here
*
ORG $B66B
INFER_TOP LDX #FUZ_OUTS ;Point at first fuzzy output
LDAA #32 ;32 fuzzy outputs
CLR_OUTS CLR 0,X ;Clear a fuzzy output
INX ;Point at next
DECA ;Loop index
BNE CLR_OUTS ;Continue till all fuzzy outs 0
LDY #RULE_START ;Point to start of 1st rule
RULE_TOP LDAA #$FF ;Begin processing rule string
STAA LOWEST_IF ;Will hold grade of min if part
IF_LOOP LDAB 0,Y ;Get rule byte 00AA AXXX; If X is A
BMI THEN_LOOP ;If MSB=1, exit to then loop
LDX #CURRENT_INS ;Point at current input data area
ANDB #$07 ;Save only input number
PSHB ;Will need input # again
ABX ;Point to specific input data
LDAA 0,X ;Get current input data
LDX #IN_MF_PTRS ;Point at offsets for input MFs
PULB ;Recover input number 0000 0XXX
ABX ;Point at pointer for this input #
LDX 0,X ;Get pointer into MF data area
LDAB 0,Y ;Get rule if part 00AA AXXX
ANDB #$38 ;00AA A000 is 8 times AAA
LSRB ;000A AA00 4 times AAA
ABX ;X points at MF points & slopes
CMPA 0,X ;Compare input data to MF pt1
BHS NOT_SEG0 ;Branch if not segment zero
CLRB ;In seg 0 grade is zero
BRA HAVE_GRADE ;Have grade of membership
NOT_SEG0 CMPA 2,X ;Compare input data to MF pt2
BHI IS_SEG2 ;Branch if segment two
LDAB 1,X ;Slope1 -> B
BEQ JAM_FF ;If vert slope, jam $FF
SUBA 0,X ;Input value - pt1 -> A
MUL ;Grade in B if D < $100
CPD #$100 ;Check for overflow
BLO HAVE_GRADE ;If < $100 grade OK in B
JAM_FF LDAB #$FF ;Else limit B to $FF
BRA HAVE_GRADE ;Have grade of membership
IS_SEG2 LDAB 3,X ;Slope2 -> B
SUBA 2,X ;Input value - pt2 -> A
MUL ;Grade in B if D < $100
CPD #$100 ;Check for overflow
BLO B_OK ;If < $100 value in B OK
LDAB #$FF ;Else limit B to $FF
B_OK LDAA #$FF ;Grade should be $FF - (B)
SBA ;Grade of membership in B
HAVE_GRADE CMPB LOWEST_IF ;Is grade lowest so far ?
BHS NOT_LOWR ;Branch if not lower
STAB LOWEST_IF ;If lower, replace lowest if
BNE NOT_LOWR ;Skip ahead if not zero
FIND_THEN INY ;Adv rule pointer to then part
LDAB 0,Y ;Get next rule byte
BPL FIND_THEN ;MSB set means its a then part
FIND_IF INY ;Adv rule pointer to if part
LDAB 0,Y ;Get next rule byte
BPL RULE_TOP ;MSB clear means its an if part
CMPB #$FF ;$FF is no more rules marker
BNE FIND_IF ;Continue looking for if or $FF
BRA DEFUZ ;When all rules done, go defuzzify
NOT_LOWR INY ;Point to next rule byte
BRA IF_LOOP ;Continue for all if parts
THEN_LOOP LDX #FUZ_OUTS ;Point at fuzzy outputs
ANDB #$1F ;Save 8 times out # + label #
ABX ;X points at fuzzy output
LDAA LOWEST_IF ;Grade of membership for rule
CMPA 0,X ;Compare to fuzzy output
BLO NOT_HIER ;Branch if not higher
STAA 0,X ;Grade is higher so update
NOT_HIER INY ;Point to next rule byte
LDAB 0,Y ;Get rule byte
BMI CHK_END ;If MSB=0 its a new rule
JMP RULE_TOP ;Else process next rule byte
CHK_END CMPB #$FF ;Check for end of rules flag
BNE THEN_LOOP ;If not $FF, must be a then part
DEFUZ LDY #SGLTN_POS ;Point at 1st output singleton
LDX #FUZ_OUTS ;Point at 1st fuzzy output
CLR COGDEX ;Loop index will run from 0->4
COG_LOOP LDAB #8 ;8 fuzzy outs per COG output
STAB SUMDEX ;Inner loop runs 8->0
LDD #$0000 ;Used for quicker clears
STD SUM_OF_FUZ ;Sum of fuzzy outputs
STD SUM_OF_PROD+1 ;Low 16-bits of sum of products
STAA SUM_OF_PROD ;Upper 8-bits
SUM_LOOP LDAB 0,X ;Get a fuzzy output
CLRA ;Clear upper 8-bits
ADDD SUM_OF_FUZ ;Add to sum of fuzzy outputs
STD SUM_OF_FUZ ;Update RAM variable
LDAA 0,X ;Get fuzzy output again
LDAB 0,Y ;Get Output singleton position
MUL ;Position times weight
ADDD SUM_OF_PROD+1 ;Low 16-bits of sum of products
STD SUM_OF_PROD+1 ;Update low 16-bits
LDAA SUM_OF_PROD ;Upper 8-bits
ADCA #0 ;Add carry from 16-bit add
STAA SUM_OF_PROD ;Upper 8-bits of 24-bit sum
INY ;Point at next singleton pos.
INX ;Point at next fuzzy output
DEC SUMDEX ;Inner loop index
BNE SUM_LOOP ;For all labels this output
PSHX ;Save index for now
CLRA ;In case divide by zero
LDX SUM_OF_FUZ ;Demominator for divide
BEQ SAV_OUT ;Branch if denominator is 0
TST SUM_OF_PROD ;See if more than 16-bit
BNE NUM_BIG ;If not zero, # is > 16-bits
LDD SUM_OF_PROD+1 ;Numerator for divide
IDIV ;Result in low 8-bits of X
XGDX ;Result now in B
TBA ;Move result to A
BRA SAV_OUT ;Go save output
NUM_BIG LDD SUM_OF_PROD ;Numerator upper 16 of 24-bit
TST SUM_OF_PROD+2 ;Check for rounding error
BPL NO_ROUND ;If MSB clear, don't round
ADDD #1 ;Round numerator up 1
NO_ROUND FDIV ;D/X -> X, use upper 8 of 16
XGDX ;Result now in A
SAV_OUT LDX #COG_OUTS ;Point to 1st defuz output
LDAB COGDEX ;Curent output number
ABX ;Point to correct output
STAA 0,X ;Update defuzzified output
PULX ;Recover index
INCB ;Increment loop index
STAB COGDEX ;Update
CMPB #4 ;Done with all four outs?
BNE COG_LOOP ;If not, continue loop
* Inference engine has completed one pass of all rules.